package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.controller.CourseAuditController;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.entity.CourseMarketDTO;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {
    @Autowired
    private CourseMarketService courseMarketService;
    /*
     * 步骤分析：
     *  1.是否需要开启事务
     *  2.判断关键数据
     *       分页数据
     *       查询条件
     *  3.构建mp分页对象
     *  4.构建查询条件对象LambdaQueryWrapper
     *  5.查询数据
     *  6.获得数据并封装返回结果
     *       封装PageVo数据
     * */
    public PageVO queryCourseList(PageRequestParams params, QueryCourseModel model,Long companyId) {
        // 1.判断业务数据
        // 1.1 判断分页数据
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(StringUtil.isNotBlank(model.getAuditStatus()),
                CourseBase::getAuditStatus, model.getAuditStatus());
        queryWrapper.like(StringUtil.isNotBlank(model.getCourseName()),
                CourseBase::getName, model.getCourseName());
        queryWrapper.eq(CourseBase::getCompanyId,companyId);
        queryWrapper.eq(CourseBase::getStatus,CommonEnum.USING_FLAG.getCode());
        // 2.创建分页数据
        Page<CourseBase> page = new Page<>(params.getPageNo(),params.getPageSize());
        // 3.根据分页和查询调价查询list数据
        if (!(ObjectUtils.nullSafeEquals(companyId,
                CourseAuditController.OPERATION_FLAG))) {
            queryWrapper.eq(CourseBase::getCompanyId, companyId);
        }
        queryWrapper.orderByDesc(CourseBase::getCreateDate);
        // 4.分页条件查询
        IPage<CourseBase> pageResult = page(page, queryWrapper);
        List<CourseBase> list = pageResult.getRecords();
        long total = pageResult.getTotal();
        // 5.将 po 数据转换为
        List<CourseBaseDTO> dtos = Collections.emptyList();
        if (!(CollectionUtils.isEmpty(list))) {
            dtos = CourseBaseConvert.INSTANCE.entitys2dtos(list);
        }
        // 6.封装PageVO数据
        PageVO pageVO = new PageVO(dtos,total,params.getPageNo(),params.getPageSize());
        return pageVO;
    }

    /**
     * 是否事务
     * 判断关键数据，判断业务数据
     * 保存
     * 查询最新数据
     * 返回
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public CourseBaseDTO createCourserBase(CourseBaseDTO dto) {



        if (StringUtil.isBlank(dto.getName())) {
            throw new RuntimeException("课程名称不能为空");
        }

        if (StringUtil.isBlank(dto.getMt())) {
            throw new RuntimeException("课程大分类不能为空");
        }

        if (StringUtil.isBlank(dto.getSt())) {
            throw new RuntimeException("课程小分类不能为空");
        }

        if (StringUtil.isBlank(dto.getGrade())) {
            throw new RuntimeException("课程等级不能为空");
        }

        if (StringUtil.isBlank(dto.getTeachmode())) {
            throw new RuntimeException("课程教学模式不能为空");
        }

        if (StringUtil.isBlank(dto.getUsers())) {
            throw new RuntimeException("使用人群不能为空");
        }

        if (StringUtil.isBlank(dto.getCharge())) {
            throw new RuntimeException("课程收费不能为空");
        }
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())){
            if (ObjectUtils.isEmpty(dto.getPrice())||dto.getPrice().floatValue()<0){
                throw new RuntimeException("收费课程，价格非法！！！");
            }
        }else {
            dto.setPrice(new BigDecimal(0));
        }
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2po(dto);
        //todo 设置为未提交
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        boolean baseResult = save(courseBase);
        if (!baseResult){
            throw new RuntimeException("课程添加失败！！");
        }
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(dto.getCharge());
        courseMarket.setPrice(dto.getPrice().floatValue());
        boolean marketResult = courseMarketService.save(courseMarket);
        if (!marketResult){
            throw new RuntimeException("营销保存失败！！！");
        }
        CourseBase base = getById(courseBase.getId());
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dTo(base);
        return courseBaseDTO;
    }

    @Override
    /**
     * 判断事务否
     * 传入参数判断
     * 是否本公司
     * 是否删除
     * 符合条件返回
     * 否则抛异常
     */
    public CourseBaseDTO getCourseBaseById(Long courseBaseId, Long companyId) {
        if (ObjectUtils.isEmpty(courseBaseId)){
            throw new RuntimeException("课程id非法!!!") ;
        }
        CourseBase courseBase = getCourseBaseByBaseId(courseBaseId, companyId);
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dTo(courseBase);
        CourseMarket market = getCourseMarketByCourseId(courseBaseId);
        courseBaseDTO.setPrice(new BigDecimal(market.getPrice().toString()));
        courseBaseDTO.setCharge(market.getCharge());
        return courseBaseDTO;
    }
    /**
     * 是否事务
     * 判断课程id是否为空
     * 判断关键数据，判断业务数据
     * 是否本公司
     * 课程是否存在
     * 判断营销数据合法
     * 课程状态是否为未提交以及审核失败
     * 是否删除
     * 转dto返回
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO dto) {
        if (ObjectUtils.isEmpty(dto.getCourseBaseId())){
            throw new RuntimeException("课程id为空！！！");
        }
        //判断课程是否在该公司存在，是否删除
        CourseBase courseBase2 = getCourseBaseByBaseId(dto.getCourseBaseId(), dto.getCompanyId());
        String status = courseBase2.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(status)||
        CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(status)||
        CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(status)){
            throw new RuntimeException("课程状态异常");
        }
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2entity(dto);
        //操作营销课程
        //
        CourseMarket market = getCourseMarketByCourseId(courseBase2.getId());
        //判断营销数据
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())){
            if (dto.getPrice().floatValue()<0){
                throw new RuntimeException("收费课程，价格非法！！！");
            }
        }else {
            dto.setPrice(new BigDecimal(0));
        }
        //若为收费，则价格需要合法
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setPrice(dto.getPrice().floatValue());
        courseMarket.setCourseId(courseBase2.getId());
        courseMarket.setCharge(dto.getCharge());
        courseMarket.setId(market.getId());
        boolean marketResult = courseMarketService.updateById(courseMarket);
        if (!marketResult){
            throw new RuntimeException("修改营销课程信息失败！！！");
        }

        courseBase.setCompanyId(null);
        courseBase.setAuditStatus(null);
        courseBase.setStatus(null);
        boolean upResult = updateById(courseBase);
        if (!upResult){
            throw new RuntimeException("修改课程信息失败");
        }
        CourseBase po= getById(courseBase.getId());
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dTo(po);
        return courseBaseDTO;
    }

    /**
     * 参数是否为空
     * 判断该公司是否有此条信息
     * 该信息状态（是否是未提交或者审核失败）
     * 是否已经删除
     * @param courseBaseId
     * @param companyId
     */
    @Override
    @Transactional
    public void removeCourseBaseById(Long courseBaseId, Long companyId) {
        if (ObjectUtils.isEmpty(courseBaseId)){
            throw new RuntimeException("请传入要删除的数据id");
        }
        CourseBase courseBase = getCourseBaseByBaseId(courseBaseId, companyId);
        String status = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(status)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(status)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(status)){
            throw new RuntimeException("课程下架后，才可以删除，课程状态异常");
        }
        if (CommonEnum.DELETE_FLAG.getCode().equals(courseBase.getStatus().toString())){
            throw new RuntimeException("已经删除！！！");
        }
        LambdaUpdateWrapper<CourseBase> courseBaseWrapper = new LambdaUpdateWrapper<>();
        courseBaseWrapper.eq(CourseBase::getId,courseBaseId);
        courseBaseWrapper.set(CourseBase::getStatus,CommonEnum.DELETE_FLAG.getCode());
        courseBaseWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        boolean baseResult =update(courseBaseWrapper);
        if (!baseResult){
            throw new RuntimeException("删除课程失败!!");
        }
        //因为数据珍贵，营销课程未做删除，其不影响查询以及其他数据
    }

    @Override
    @Transactional
    public void commitCourseBase(Long courseId, Long companyId) {
        if (ObjectUtils.isEmpty(courseId)||
                ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 2.判断业务数据
        // 课程基础信息
        // 判断是否存在
        // 判断是否是同一家教学机构
        // 判断是否删除
        // 判断审核状态
        getCourseByLogic(companyId, courseId);
        // 3.修改课程审核状态
        // 已提交
        // createDate changeDate 使用MP自动填充来完成
        // UpdateWrapper 会将MP的自动填充功能失效
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus,
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(CourseBase::getId, courseId);
        boolean result = this.update(updateWrapper);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }
    }

    @Override
    @Transactional
    public void approve(CourseBaseDTO dto) {
        // 1.判断关键数据
        // auditMind auditStatus courseid
        if (StringUtil.isBlank(dto.getAuditMind())||
                StringUtil.isBlank(dto.getAuditStatus())||
                ObjectUtils.isEmpty(dto.getCourseBaseId())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 2.判断业务数据
        // 课程基础信息
        // 判断是否存在
        // 判断是否删除
        // 判断审核状态
        // 必须为：已提交
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getId, dto.getCourseBaseId());
        queryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        queryWrapper.eq(CourseBase::getAuditStatus,
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());
        int count = this.count(queryWrapper);
        if (count < 1) {
            ExceptionCast.cast(ContentErrorCode.E_120023);
        }
        // 审核状态
        // 运营平台只能给课程审核状态赋值：审核通过、审核未通过
        String auditStatus = dto.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120016);
        }
        // 3.修改课程审核信息
        // auditMind auditStatus auditNum（每次+1）
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus, dto.getAuditStatus());
        updateWrapper.set(CourseBase::getAuditMind, dto.getAuditMind());
        // 使用redis来实现
        // updateWrapper.set(CourseBase::getAuditNums, dto.getAuditMind());
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(CourseBase::getId, dto.getCourseBaseId());
        boolean result = this.update(updateWrapper);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }

    }

    private void getCourseByLogic(Long companyId, Long courseBaseId) {
        CourseBase courseBase = getCourseBaseByBaseId(courseBaseId, companyId);
        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }
    }

    /**
     * 判断以及查询营销课程
     * @param courseBaseId
     * @return
     */
    private CourseMarket getCourseMarketByCourseId(Long courseBaseId) {
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = new LambdaQueryWrapper<>();
        marketQueryWrapper.eq(CourseMarket::getCourseId, courseBaseId);

        CourseMarket courseMarket = courseMarketService.getOne(marketQueryWrapper);

        if (ObjectUtils.isEmpty(courseMarket)) {
            throw new RuntimeException("课程营销数据不存在");
        }
        return courseMarket;
    }

    /**
     * 查询此公司是否有该课程
     * 有则返回
     * 没有就抛异常
     * @param courseBaseId
     * @param companyId
     * @return
     */
    public CourseBase getCourseBaseByBaseId(Long courseBaseId, Long companyId) {
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getCompanyId,companyId);
        queryWrapper.eq(CourseBase::getId,courseBaseId);
        CourseBase courseBase = getOne(queryWrapper);
        if (ObjectUtils.isEmpty(courseBase)){
            throw new RuntimeException("课程不存在");
        }
        Integer status = courseBase.getStatus();
        if (CommonEnum.DELETE_FLAG.getCode().equals(status)){
            throw new RuntimeException("课程已经删除了！！！");
        }
        return courseBase;
    }




}
